package cuishifeng.blog.learn.lambda.function;

import java.util.function.BiConsumer;
import java.util.function.BiFunction;

import cuishifeng.blog.learn.lambda.function.ServiceFunction.FourFunction;
import cuishifeng.blog.learn.lambda.function.ServiceFunction.ThreeFunction;
import lombok.Data;

/**
 * @author cuishifeng <cuishifeng0207@163.com>
 * Created on 2021-04-13
 */
public class FunctionDemo {

    public static void main(String[] args) {
        FunctionDemo functionDemo = new FunctionDemo();
        BiFunction<String, Integer, String> function = functionDemo::get;

        String result = function.apply("123", 1);
        System.out.println("result:" + result);

        ThreeFunction<FunctionDemo, String, Integer, String> threeFunction = FunctionDemo::get;

        String result2 = threeFunction.apply(functionDemo, "hello", 1);
        System.out.println("threeFunction:" + result2);

        FourFunction<FunctionDemo, String, String, Integer, String> fourFunction = FunctionDemo::get;

        String fourResult = fourFunction.apply(functionDemo, "hello", "go", 1);
        System.out.println("fourFunction:" + fourResult);


        BiFunction<FunctionDemo, String, String> function3 = FunctionDemo::get2;
        String result3 = function3.apply(functionDemo, "hello2");
        System.out.println("result3:" + result3);


        TwoServiceFunction<FunctionDemo, String, Integer, String> function4 = FunctionDemo::get;
        String result4 = function4.apply(functionDemo, "hello3", 123456);
        System.out.println("result4:" + result4);


    }

    public String get(String name, Integer num) {
        return name + num;
    }

    public String get(String name, String v2, Integer num) {
        return name + v2 + num;
    }

    public String get2(String name) {
        return name;
    }

    public <T, R> R execute(T t, BiFunction<FunctionDemo, T, R> biFunction) {
        FunctionDemo functionDemo = new FunctionDemo();
        return biFunction.apply(functionDemo, t);
    }

    @Data
    public static class Info<T, R> {
        BiFunction<FunctionDemo, T, R> biFunction;
    }

    public static class InfoBuilder<T, R> {
        private Info info;

        public InfoBuilder() {
            this.info = new Info();
        }

        public static InfoBuilder newBuilder() {
            return new InfoBuilder();
        }

        public <T, R> InfoBuilder set(BiFunction<FunctionDemo, T, R> biFunction) {
            BiConsumer<Info, BiFunction<FunctionDemo, T, R>> consumer = Info::setBiFunction;
            consumer.accept(info, biFunction);
            return this;
        }

        public Info build() {
            return info;
        }

    }

}
